/*
 * =====================================================================================
 *
 *       Filename:  CompareAndExchangeBool.h
 *
 *    Description:  CompareAndExchangeBool.h
 *
 *         Author:  Younghyun Jo
 *   Organization:  Master Student
 *                  Computer Systems and Platforms Laboratory
 *                  Department of Computer Science and Engineering
 *
 * =====================================================================================
 */

#ifndef PARTICIPANT
  #define PARTICIPANT Participant
#endif

#include <sys/time.h>

inline int atomic_fetch_and_add(int* mem, int increment) {
  return __sync_fetch_and_add(mem, increment);
}

inline int atomic_add_and_fetch(int* mem, int increment) {
  int oldValue = __sync_fetch_and_add(mem, increment);
  //int oldValue = __insn_fetchadd(mem, increment);
  return oldValue + increment;
}

/**
 * @return the old value of *ptr
 */
inline int atomic_compare_and_swap_val(int* ptr, int oldValue, int newValue) {
  return __sync_val_compare_and_swap(ptr, oldValue, newValue);
  //return arch_atomic_val_compare_and_exchange(ptr, oldValue, newValue);
}

/**
 * @return true if CAS was sucessful
 */
inline bool atomic_compare_and_swap_bool(int* ptr, int oldValue, int newValue) {
  return __sync_bool_compare_and_swap(ptr, oldValue, newValue);
  //return arch_atomic_bool_compare_and_exchange(ptr, oldValue, newValue);
}

inline void memory_fence() {
  __asm__ __volatile__ ("mfence" : : : "memory");
  //tmc_mem_fence();
}

class Participant;

class CompareAndExchangeBool {
  public:
    CompareAndExchangeBool(const int numParticipants) {}
    ~CompareAndExchangeBool() {}

    inline void finalize_initialization() {}

    int sharedVar;
};

class Participant {
  public:
    Participant(CompareAndExchangeBool* const compareAndExchangeBool)
      : _compareAndExchangeBool(compareAndExchangeBool) {}

    inline bool synchronize() const {
      int prevVal = _compareAndExchangeBool->sharedVar;
      int newVal = prevVal + 1;
      bool val = atomic_compare_and_swap_bool(&(_compareAndExchangeBool->sharedVar), prevVal, newVal);
      return true;
    }

  private:
    CompareAndExchangeBool* const _compareAndExchangeBool;
};

